"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getApkInfo = exports.Platform = exports.Device = exports.generateFullDevice = exports.generateShortDevice = void 0;
const crypto_1 = require("crypto");
const constants_1 = require("./constants");
const crypto_2 = __importDefault(require("crypto"));
const axios_1 = __importDefault(require("axios"));
function initPublicKey(pemStr, encryptKey) {
    const publicKey = crypto_2.default.createPublicKey(pemStr);
    return crypto_2.default.publicEncrypt({
        key: publicKey, padding: crypto_2.default.constants.RSA_PKCS1_PADDING
    }, Buffer.from(encryptKey)).toString('base64');
}
function sign(key, params, ts, nonce, secret) {
    const md5 = crypto_2.default.createHash('md5');
    return md5.update(key + params + ts + nonce + secret).digest('hex');
}
function aesEncrypt(data, key) {
    const iv = key.substring(0, 16);
    const cipher = crypto_2.default.createCipheriv('aes-128-cbc', key, iv);
    let encrypted = cipher.update(data);
    return Buffer.concat([encrypted, cipher.final()]);
    ;
}
function aesDecrypt(encryptedData, key) {
    const iv = key.substring(0, 16);
    let encryptedText = Buffer.from(encryptedData, 'base64');
    let decipher = crypto_2.default.createDecipheriv('aes-128-cbc', key, iv);
    let decrypted = decipher.update(encryptedText);
    decrypted = Buffer.concat([decrypted, decipher.final()]);
    return decrypted.toString();
}
function generateImei(uin) {
    let imei = uin % 2 ? "86" : "35";
    const buf = Buffer.alloc(4);
    buf.writeUInt32BE(uin);
    let a = buf.readUInt16BE();
    let b = Buffer.concat([Buffer.alloc(1), buf.slice(1)]).readUInt32BE();
    if (a > 9999)
        a = Math.trunc(a / 10);
    else if (a < 1000)
        a = String(uin).substr(0, 4);
    while (b > 9999999)
        b = b >>> 1;
    if (b < 1000000)
        b = String(uin).substr(0, 4) + String(uin).substr(0, 3);
    imei += a + "0" + b;
    function calcSP(imei) {
        let sum = 0;
        for (let i = 0; i < imei.length; ++i) {
            if (i % 2) {
                let j = parseInt(imei[i]) * 2;
                sum += j % 10 + Math.floor(j / 10);
            }
            else {
                sum += parseInt(imei[i]);
            }
        }
        return (100 - sum) % 10;
    }
    return imei + calcSP(imei);
}
/** 生成短设备信息 */
function generateShortDevice() {
    const randstr = (length, num = false) => {
        const map = num ? '0123456789' : '0123456789abcdef';
        return (0, constants_1.randomString)(length, map);
    };
    return {
        "--begin--": "该设备为随机生成，丢失后不能得到原先配置",
        product: `ILPP-${randstr(5).toUpperCase()}`,
        device: `${randstr(5).toUpperCase()}`,
        board: `${randstr(5).toUpperCase()}`,
        brand: `${randstr(4).toUpperCase()}`,
        model: `ILPP ${randstr(4).toUpperCase()}`,
        wifi_ssid: `HUAWEI-${randstr(7)}`,
        bootloader: `U-boot`,
        android_id: `IL.${randstr(7, true)}.${randstr(4, true)}`,
        boot_id: `${randstr(8)}-${randstr(4)}-${randstr(4)}-${randstr(4)}-${randstr(12)}`,
        proc_version: `Linux version 5.10.101-android12-${randstr(8)}`,
        mac_address: `2D:${randstr(2).toUpperCase()}:${randstr(2).toUpperCase()}:${randstr(2).toUpperCase()}:${randstr(2).toUpperCase()}:${randstr(2).toUpperCase()}`,
        ip_address: `192.168.${randstr(2, true)}.${randstr(2, true)}`,
        imei: `86${randstr(13, true)}`,
        incremental: `${randstr(10).toUpperCase()}`,
        "--end--": "修改后可能需要重新验证设备。"
    };
}
exports.generateShortDevice = generateShortDevice;
/** 生成完整设备信息 */
function generateFullDevice(apk, d) {
    if (!d)
        d = generateShortDevice();
    return {
        display: d.android_id,
        product: d.product,
        device: d.device,
        board: d.board,
        brand: d.brand,
        model: d.model,
        bootloader: d.bootloader,
        fingerprint: `${d.brand}/${d.product}/${d.device}:10/${d.android_id}/${d.incremental}:user/release-keys`,
        boot_id: d.boot_id,
        proc_version: d.proc_version,
        baseband: "",
        sim: "T-Mobile",
        os_type: "android",
        mac_address: d.mac_address,
        ip_address: d.ip_address,
        wifi_bssid: d.mac_address,
        wifi_ssid: d.wifi_ssid,
        imei: d.imei,
        android_id: d.android_id,
        apn: "wifi",
        version: {
            incremental: d.incremental,
            release: "10",
            codename: "REL",
            sdk: 29,
        },
        imsi: (0, crypto_1.randomBytes)(16),
        guid: (0, constants_1.md5)(Buffer.concat([Buffer.from(d.imei), Buffer.from(d.mac_address)])),
    };
}
exports.generateFullDevice = generateFullDevice;
class Device {
    constructor(apk, d) {
        this.apk = apk;
        this.secret = "ZdJqM15EeO2zWc08";
        this.publicKey = `-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDEIxgwoutfwoJxcGQeedgP7FG9
qaIuS0qzfR8gWkrkTZKM2iWHn2ajQpBRZjMSoSf6+KJGvar2ORhBfpDXyVtZCKpq
LQ+FLkpncClKVIrBwv6PHyUvuCb0rIarmgDnzkfQAqVufEtR64iazGDKatvJ9y6B
9NMbHddGSAUmRTCrHQIDAQAB
-----END PUBLIC KEY-----`;
        if (!d)
            d = generateShortDevice();
        Object.assign(this, generateFullDevice(apk, d));
    }
    async getQIMEI() {
        if (this.apk.app_key === "") {
            return;
        }
        const k = (0, constants_1.randomString)(16, "abcdef1234567890");
        const key = initPublicKey(this.publicKey, k);
        const time = Date.now();
        const nonce = (0, constants_1.randomString)(16, "abcdef1234567890");
        const payload = this.genRandomPayloadByDevice();
        const params = aesEncrypt(JSON.stringify(payload), k).toString('base64');
        const { data } = await axios_1.default.post("https://snowflake.qq.com/ola/android", {
            key,
            params,
            time, nonce,
            sign: sign(key, params, time, nonce, this.secret),
            extra: ''
        }, {
            headers: {
                'User-Agent': `Dalvik/2.1.0 (Linux; U; Android ${this.version.release}; PCRT00 Build/N2G48H)`,
                'Content-Type': "application/json"
            }
        });
        if (data?.code !== 0) {
            return;
        }
        try {
            const { q16, q36 } = JSON.parse(aesDecrypt(data.data, k));
            this.qImei16 = q16;
            this.qImei36 = q36;
        }
        catch { }
    }
    genRandomPayloadByDevice() {
        const now = new Date();
        const fixedRand = (max = 1, min = 0) => {
            if (max < min)
                [max, min] = [min, max];
            const diff = max - min;
            return Math.floor(Math.random() * diff) + min;
        };
        const reserved = {
            "harmony": "0",
            "clone": "0",
            "containe": "",
            "oz": "UhYmelwouA+V2nPWbOvLTgN2/m8jwGB+yUB5v9tysQg=",
            "oo": "Xecjt+9S1+f8Pz2VLSxgpw==",
            "kelong": "0",
            "uptimes": new Date().toISOString()
                .replace('T', ' ')
                .replace(/\.\d+Z/, ''),
            "multiUser": "0",
            "bod": this.board,
            "brd": this.brand,
            "dv": this.device,
            "firstLevel": "",
            "manufact": this.brand,
            "name": this.model,
            "host": "se.infra",
            "kernel": this.fingerprint
        };
        const timeMonth = now.toISOString().slice(0, 7) + "-01";
        const rand1 = fixedRand(900000, 100000);
        const rand2 = fixedRand(900000000, 100000000);
        let beaconIdArr = new Array(40).fill(1).map((_, i) => {
            if ([1, 2, 13, 14, 17, 18, 21, 22, 25, 26, 29, 30, 33, 34, 37, 38].includes(i))
                return `k${i}:${timeMonth}${rand1}.${rand2}`;
            if (i === 3)
                return "k3:0000000000000000";
            if (i === 4)
                return `k4:${(0, constants_1.randomString)(16, "123456789abcdef")}`;
            return `k${i}:${fixedRand(10000)}`;
        });
        return {
            "androidId": '',
            "platformId": 1,
            "appKey": this.apk.app_key,
            "appVersion": this.apk.version,
            "beaconIdSrc": beaconIdArr.join(';'),
            "brand": this.brand,
            "channelId": "2017",
            "cid": "",
            "imei": this.imei,
            "imsi": '',
            "mac": this.mac_address,
            "model": this.model,
            "networkType": "unknown",
            "oaid": "",
            "osVersion": `Android ${this.version.release},level ${this.version.sdk}`,
            "qimei": "",
            "qimei36": "",
            "sdkVersion": this.apk.sdkver,
            "targetSdkVersion": "26",
            "audit": "",
            "userId": "{}",
            "packageId": this.apk.id,
            "deviceType": this.display,
            "sdkName": "",
            "reserved": JSON.stringify(reserved),
        };
    }
}
exports.Device = Device;
/** 支持的登录设备平台 */
var Platform;
(function (Platform) {
    Platform[Platform["Android"] = 1] = "Android";
    Platform[Platform["aPad"] = 2] = "aPad";
    Platform[Platform["Watch"] = 3] = "Watch";
    Platform[Platform["iMac"] = 4] = "iMac";
    Platform[Platform["iPad"] = 5] = "iPad";
})(Platform = exports.Platform || (exports.Platform = {}));
const mobile = {
    id: "com.tencent.mobileqq",
    app_key: '0S200MNJT807V3GE',
    name: "A8.9.50.10650",
    version: "8.9.50.10650",
    ver: "8.9.50",
    sign: Buffer.from([166, 183, 69, 191, 36, 162, 194, 119, 82, 119, 22, 246, 243, 110, 182, 141]),
    buildtime: 1676531414,
    appid: 16,
    subid: 537155551,
    bitmap: 150470524,
    sigmap: 16724722,
    sdkver: "6.0.0.2535",
    display: "Android",
    ssover: 19,
};
const watch = {
    id: "com.tencent.qqlite",
    app_key: '0S200MNJT807V3GE',
    name: "A2.0.5",
    version: "2.0.5",
    ver: "2.0.5",
    sign: Buffer.from([166, 183, 69, 191, 36, 162, 194, 119, 82, 119, 22, 246, 243, 110, 182, 141]),
    buildtime: 1559564731,
    appid: 16,
    subid: 537064446,
    bitmap: 16252796,
    sigmap: 34869472,
    sdkver: "6.0.0.236",
    display: "Watch",
    ssover: 5
};
const hd = {
    id: "com.tencent.minihd.qq",
    app_key: '0S200MNJT807V3GE',
    name: "A5.9.3.3468",
    version: "5.9.3.3468",
    ver: "5.9.3",
    sign: Buffer.from([170, 57, 120, 244, 31, 217, 111, 249, 145, 74, 102, 158, 24, 100, 116, 199]),
    buildtime: 1637427966,
    appid: 16,
    subid: 537067382,
    bitmap: 150470524,
    sigmap: 1970400,
    sdkver: "6.0.0.2487",
    display: "aPad",
    ssover: 12
};
const apklist = {
    [Platform.Android]: mobile,
    [Platform.aPad]: hd,
    [Platform.Watch]: watch,
    [Platform.iMac]: { ...hd },
    [Platform.iPad]: { ...hd },
};
apklist[Platform.aPad].subid = 537150493;
apklist[Platform.iMac].subid = 537128930;
apklist[Platform.iMac].display = "iMac";
apklist[Platform.iPad].subid = 537155074;
apklist[Platform.iPad].display = "iPad";
function getApkInfo(p) {
    return apklist[p] || apklist[Platform.Android];
}
exports.getApkInfo = getApkInfo;
